load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test")
load("//bazel:canbench.bzl", "rust_canbench")
load("//bazel:canisters.bzl", "rust_canister")
load("//bazel:defs.bzl", "rust_ic_test")

package(default_visibility = ["//visibility:public"])

[
    rust_library(
        name = "ledger" + name_suffix,
        srcs = glob(["src/**/*.rs"]),
        compile_data = [
            "//rs/ledger_suite/icrc1/archive:archive_canister" + archive_name_suffix,
        ],
        crate_features = features,
        crate_name = "ic_icrc1_ledger",
        proc_macro_deps = [
            # Keep sorted.
            "@crate_index//:async-trait",
            "@crate_index//:test-strategy",
        ],
        rustc_env = {
            "IC_ICRC1_ARCHIVE_WASM_PATH": "$(execpath //rs/ledger_suite/icrc1/archive:archive_canister" + archive_name_suffix + ")",
        },
        version = "0.9.0",
        deps = [
            # Keep sorted.
            "//packages/ic-ledger-hash-of:ic_ledger_hash_of",
            "//packages/icrc-ledger-types:icrc_ledger_types",
            "//rs/ledger_suite/common/ledger_canister_core",
            "//rs/ledger_suite/common/ledger_core",
            "//rs/ledger_suite/icrc1",
            "//rs/rust_canisters/canister_log",
            "//rs/types/base_types",
            "@crate_index//:candid",
            "@crate_index//:ciborium",
            "@crate_index//:hex",
            "@crate_index//:ic-cdk",
            "@crate_index//:ic-certification",
            "@crate_index//:ic-metrics-encoder",
            "@crate_index//:ic-stable-structures",
            "@crate_index//:leb128",
            "@crate_index//:minicbor",
            "@crate_index//:serde",
            "@crate_index//:serde_bytes",
        ] + extra_deps,
    )
    for (name_suffix, archive_name_suffix, features, extra_deps) in [
        (
            "",
            "",
            [],
            [
                "//rs/ledger_suite/icrc1/tokens_u64",
            ],
        ),
        (
            "_u256",
            "_u256",
            ["u256-tokens"],
            [
                "//rs/ledger_suite/icrc1/tokens_u256",
            ],
        ),
        (
            "_canbench",
            "",
            ["canbench-rs"],
            [
                "//rs/ledger_suite/icrc1/tokens_u64",
                "@crate_index//:canbench-rs",
            ],
        ),
        (
            "_canbench_u256",
            "_u256",
            [
                "canbench-rs",
                "u256-tokens",
            ],
            [
                "//rs/ledger_suite/icrc1/tokens_u256",
                "@crate_index//:canbench-rs",
            ],
        ),
        (
            "_nextledgerversion",
            "",
            ["next-ledger-version"],
            [
                "//rs/ledger_suite/icrc1/tokens_u64",
            ],
        ),
        (
            "_u256_nextledgerversion",
            "_u256",
            [
                "next-ledger-version",
                "u256-tokens",
            ],
            [
                "//rs/ledger_suite/icrc1/tokens_u256",
            ],
        ),
    ]
]

[
    rust_canister(
        name = "ledger_canister" + name_suffix,
        srcs = ["src/main.rs"] + glob(["src/benches/**/*.rs"]),
        crate_features = features,
        crate_name = "ic_icrc1_ledger_canister" + name_suffix,
        opt = "z",
        proc_macro_deps = [
            # Keep sorted.
        ],
        service_file = ":ledger.did",
        deps = [
            # Keep sorted.
            "//packages/ic-http-types",
            "//packages/icrc-ledger-types:icrc_ledger_types",
            "//rs/ledger_suite/common/ledger_canister_core",
            "//rs/ledger_suite/common/ledger_core",
            "//rs/ledger_suite/icrc1",
            "//rs/rust_canisters/canister_log",
            "//rs/types/base_types",
            "@crate_index//:candid",
            "@crate_index//:ciborium",
            "@crate_index//:ic-cdk",
            "@crate_index//:ic-cdk-timers",
            "@crate_index//:ic-certification",
            "@crate_index//:ic-metrics-encoder",
            "@crate_index//:ic-stable-structures",
            "@crate_index//:num-traits",
            "@crate_index//:serde_bytes",
        ] + extra_deps,
    )
    for (name_suffix, features, extra_deps) in [
        (
            "",
            [],
            [
                ":ledger",
                "//rs/ledger_suite/icrc1/tokens_u64",
            ],
        ),
        (
            "_canbench",
            ["canbench-rs"],
            [
                ":ledger",
                "//rs/ledger_suite/icrc1/tokens_u64",
                "@crate_index//:assert_matches",
                "@crate_index//:canbench-rs",
            ],
        ),
        (
            "_u256",
            ["u256-tokens"],
            [
                ":ledger_u256",
                "//rs/ledger_suite/icrc1/tokens_u256",
            ],
        ),
        (
            "_u256_canbench",
            [
                "u256-tokens",
                "canbench-rs",
            ],
            [
                ":ledger_u256",
                "//rs/ledger_suite/icrc1/tokens_u256",
                "@crate_index//:assert_matches",
                "@crate_index//:canbench-rs",
            ],
        ),
        (
            "_getblocksdisabled",
            ["get-blocks-disabled"],
            [
                ":ledger",
                "//rs/ledger_suite/icrc1/tokens_u64",
            ],
        ),
        (
            "_u256_getblocksdisabled",
            [
                "get-blocks-disabled",
                "u256-tokens",
            ],
            [
                ":ledger_u256",
                "//rs/ledger_suite/icrc1/tokens_u256",
            ],
        ),
        (
            "_nextledgerversion",
            [],
            [
                ":ledger_nextledgerversion",
                "//rs/ledger_suite/icrc1/tokens_u64",
            ],
        ),
        (
            "_u256_nextledgerversion",
            [
                "u256-tokens",
            ],
            [
                ":ledger_u256_nextledgerversion",
                "//rs/ledger_suite/icrc1/tokens_u256",
            ],
        ),
        (
            "_lowupgradeinstructionlimits",
            ["low-upgrade-instruction-limits"],
            [
                ":ledger",
                "//rs/ledger_suite/icrc1/tokens_u64",
            ],
        ),
        (
            "_u256_lowupgradeinstructionlimits",
            [
                "low-upgrade-instruction-limits",
                "u256-tokens",
            ],
            [
                ":ledger_u256",
                "//rs/ledger_suite/icrc1/tokens_u256",
            ],
        ),
    ]
]

[
    rust_test(
        name = "ledger_canister_test" + name_suffix,
        crate = ":_wasm_ledger_canister" + name_suffix,
        crate_features = features,
        data = [
            ":ledger.did",
        ],
        env = {
            "CARGO_MANIFEST_DIR": "rs/ledger_suite/icrc1/ledger",
        },
        deps = ["@crate_index//:candid_parser"] + extra_deps,
    )
    for (name_suffix, features, extra_deps) in [
        (
            "",
            [],
            [
                "//rs/ledger_suite/icrc1/tokens_u64",
            ],
        ),
        (
            "_u256",
            ["u256-tokens"],
            [
                "//rs/ledger_suite/icrc1/tokens_u256",
            ],
        ),
    ]
]

[
    rust_ic_test(
        name = "ledger_test" + name_suffix,
        timeout = "long",
        srcs = ["tests/tests.rs"],
        crate_features = features,
        data = [
            ":block.cddl",
            ":ledger_canister" + name_suffix + ".wasm.gz",
            ":ledger_canister" + name_suffix + "_lowupgradeinstructionlimits.wasm.gz",
            ":ledger_canister" + name_suffix + "_nextledgerversion.wasm.gz",
            "//rs/ledger_suite/icrc1/archive:archive_canister" + name_suffix + ".wasm.gz",
            "//rs/universal_canister/impl:universal_canister.wasm.gz",
            "@mainnet_canisters//:ck_btc_ledger.wasm.gz",
            "@mainnet_canisters//:ck_btc_ledger_v1.wasm.gz",
            "@mainnet_canisters//:ck_btc_ledger_v2.wasm.gz",
            "@mainnet_canisters//:ck_btc_ledger_v2_noledgerversion.wasm.gz",
            "@mainnet_canisters//:ck_btc_ledger_v3.wasm.gz",
            "@mainnet_canisters//:ck_eth_ledger.wasm.gz",
            "@mainnet_canisters//:ck_eth_ledger_v1.wasm.gz",
            "@mainnet_canisters//:ck_eth_ledger_v2.wasm.gz",
            "@mainnet_canisters//:ck_eth_ledger_v2_noledgerversion.wasm.gz",
            "@mainnet_canisters//:ck_eth_ledger_v3.wasm.gz",
            "@mainnet_canisters//:sns_ledger.wasm.gz",
        ],
        env = {
            "CARGO_MANIFEST_DIR": "rs/ledger_suite/icrc1/ledger",
            "CKBTC_IC_ICRC1_LEDGER_DEPLOYED_VERSION_WASM_PATH": "$(rootpath @mainnet_canisters//:ck_btc_ledger.wasm.gz)",
            "CKBTC_IC_ICRC1_LEDGER_V1_VERSION_WASM_PATH": "$(rootpath @mainnet_canisters//:ck_btc_ledger_v1.wasm.gz)",
            "CKBTC_IC_ICRC1_LEDGER_V2_VERSION_WASM_PATH": "$(rootpath @mainnet_canisters//:ck_btc_ledger_v2.wasm.gz)",
            "CKBTC_IC_ICRC1_LEDGER_V2_NOLEDGERLEVRION_VERSION_WASM_PATH": "$(rootpath @mainnet_canisters//:ck_btc_ledger_v2_noledgerversion.wasm.gz)",
            "CKBTC_IC_ICRC1_LEDGER_V3_VERSION_WASM_PATH": "$(rootpath @mainnet_canisters//:ck_btc_ledger_v3.wasm.gz)",
            "CKETH_IC_ICRC1_LEDGER_DEPLOYED_VERSION_WASM_PATH": "$(rootpath @mainnet_canisters//:ck_eth_ledger.wasm.gz)",
            "CKETH_IC_ICRC1_LEDGER_V1_VERSION_WASM_PATH": "$(rootpath @mainnet_canisters//:ck_eth_ledger_v1.wasm.gz)",
            "CKETH_IC_ICRC1_LEDGER_V2_VERSION_WASM_PATH": "$(rootpath @mainnet_canisters//:ck_eth_ledger_v2.wasm.gz)",
            "CKETH_IC_ICRC1_LEDGER_V2_NOLEDGERLEVRION_VERSION_WASM_PATH": "$(rootpath @mainnet_canisters//:ck_eth_ledger_v2_noledgerversion.wasm.gz)",
            "CKETH_IC_ICRC1_LEDGER_V3_VERSION_WASM_PATH": "$(rootpath @mainnet_canisters//:ck_eth_ledger_v3.wasm.gz)",
            "IC_ICRC1_ARCHIVE_WASM_PATH": "$(rootpath //rs/ledger_suite/icrc1/archive:archive_canister" + name_suffix + ".wasm.gz)",
            "IC_ICRC1_LEDGER_DEPLOYED_VERSION_WASM_PATH": "$(rootpath @mainnet_canisters//:sns_ledger.wasm.gz)",
            "IC_ICRC1_LEDGER_WASM_PATH": "$(rootpath :ledger_canister" + name_suffix + ".wasm.gz)",
            "IC_ICRC1_LEDGER_WASM_INSTR_LIMITS_PATH": "$(rootpath :ledger_canister" + name_suffix + "_lowupgradeinstructionlimits.wasm.gz)",
            "IC_ICRC1_LEDGER_NEXT_VERSION_WASM_PATH": "$(rootpath :ledger_canister" + name_suffix + "_nextledgerversion.wasm.gz)",
            "UNIVERSAL_CANISTER_WASM_PATH": "$(rootpath //rs/universal_canister/impl:universal_canister.wasm.gz)",
        },
        deps = [
            # Keep sorted.
            ":ledger",
            "//packages/ic-ledger-hash-of:ic_ledger_hash_of",
            "//packages/icrc-ledger-types:icrc_ledger_types",
            "//rs/ledger_suite/icrc1",
            "//rs/ledger_suite/tests/sm-tests:ic-ledger-suite-state-machine-tests" + name_suffix,
            "//rs/ledger_suite/common/ledger_canister_core",
            "//rs/ledger_suite/common/ledger_core",
            "//rs/ledger_suite/icrc1/test_utils",
            "//rs/ledger_suite/test_utils/in_memory_ledger:ic-ledger-suite-in-memory-ledger" + name_suffix,
            "//rs/ledger_suite/test_utils/state_machine_helpers:ic-ledger-suite-state-machine-helpers",
            "//rs/ledger_suite/tests/sm-tests/constants:ic-ledger-suite-state-machine-tests-constants",
            "//rs/state_machine_tests",
            "//rs/test_utilities/load_wasm",
            "//rs/types/base_types",
            "@crate_index//:assert_matches",
            "@crate_index//:candid",
            "@crate_index//:cddl",
            "@crate_index//:ciborium",
            "@crate_index//:hex",
            "@crate_index//:ic-agent",
            "@crate_index//:ic-cbor",
            "@crate_index//:ic-certification",
            "@crate_index//:ic-metrics-encoder",
            "@crate_index//:leb128",
            "@crate_index//:num-bigint",
            "@crate_index//:num-traits",
            "@crate_index//:proptest",
            "@crate_index//:rand",
            "@crate_index//:serde_bytes",
        ] + extra_deps,
    )
    for (name_suffix, features, extra_deps) in [
        (
            "",
            [],
            ["//rs/ledger_suite/icrc1/tokens_u64"],
        ),
        (
            "_u256",
            ["u256-tokens"],
            ["//rs/ledger_suite/icrc1/tokens_u256"],
        ),
    ]
]

[
    rust_test(
        name = "ledger_unit_test" + name_suffix,
        compile_data = [
            "//rs/ledger_suite/icrc1/archive:archive_canister.wasm.gz",
        ],
        crate = "ledger",
        crate_features = features,
        deps = [
            # Keep sorted.
            ":ledger" + name_suffix,
            "//packages/icrc-ledger-types:icrc_ledger_types",
            "//rs/ledger_suite/common/ledger_canister_core",
            "//rs/ledger_suite/common/ledger_core",
            "//rs/ledger_suite/icrc1",
            "//rs/ledger_suite/tests/sm-tests:ic-ledger-suite-state-machine-tests",
            "//rs/ledger_suite/tests/sm-tests/constants:ic-ledger-suite-state-machine-tests-constants",
            "//rs/types/base_types",
            "@crate_index//:proptest",
        ] + extra_deps,
    )
    for (name_suffix, features, extra_deps) in [
        (
            "",
            [],
            [],
        ),
        (
            "_u256",
            ["u256-tokens"],
            ["//rs/ledger_suite/icrc1/tokens_u256"],
        ),
    ]
]

# Usage:
# Benchmarking:
# * bazel run //rs/ledger_suite/icrc1/ledger:canbench_u64 for legder using u64 tokens.
# * bazel run //rs/ledger_suite/icrc1/ledger:canbench_u256 for legder using u256 tokens.
# Testing:
# * bazel test //rs/ledger_suite/icrc1/ledger:canbench_u64_test for legder using u64 tokens.
# * bazel test //rs/ledger_suite/icrc1/ledger:canbench_u256_test for legder using u256 tokens.
# Updating the results file:
# * bazel run //rs/ledger_suite/icrc1/ledger:canbench_u64_update for updating the results file.
# * bazel run //rs/ledger_suite/icrc1/ledger:canbench_u256_update for updating the results file.
#  If the performance change is expected, run these targets to save the updated benchmark results.
[
    rust_canbench(
        name = "canbench" + name_suffix,
        srcs = glob(["src/**/*.rs"]),
        add_test = True,
        crate_features = features,
        proc_macro_deps = [
            # Keep sorted.
        ],
        results_file = "canbench_results/canbench" + name_suffix + ".yml",
        deps = [
            # Keep sorted.
            "//packages/ic-http-types",
            "//packages/icrc-ledger-types:icrc_ledger_types",
            "//rs/ledger_suite/common/ledger_canister_core",
            "//rs/ledger_suite/common/ledger_core",
            "//rs/ledger_suite/icrc1",
            "//rs/rust_canisters/canister_log",
            "//rs/types/base_types",
            "@crate_index//:assert_matches",
            "@crate_index//:candid",
            "@crate_index//:ciborium",
            "@crate_index//:ic-cdk",
            "@crate_index//:ic-cdk-timers",
            "@crate_index//:ic-metrics-encoder",
            "@crate_index//:ic-stable-structures",
            "@crate_index//:num-traits",
            "@crate_index//:serde_bytes",
        ] + extra_deps,
    )
    for (name_suffix, features, extra_deps) in [
        (
            "_u64",
            ["canbench-rs"],
            [
                ":ledger_canbench",
                "//rs/ledger_suite/icrc1/tokens_u64",
                "@crate_index//:canbench-rs",
            ],
        ),
        (
            "_u256",
            [
                "canbench-rs",
                "u256-tokens",
            ],
            [
                ":ledger_canbench_u256",
                "//rs/ledger_suite/icrc1/tokens_u256",
                "@crate_index//:canbench-rs",
            ],
        ),
    ]
]

rust_ic_test(
    name = "ledger_upgrade_token_type_tests",
    srcs = ["tests/upgrade_token_type_tests.rs"],
    crate_features = [],
    data = [
        ":ledger_canister.wasm.gz",
        ":ledger_canister_u256.wasm.gz",
        "@mainnet_canisters//:ck_btc_ledger.wasm.gz",
        "@mainnet_canisters//:ck_eth_ledger.wasm.gz",
    ],
    env = {
        "IC_ICRC1_LEDGER_WASM_U64_PATH": "$(rootpath :ledger_canister.wasm.gz)",
        "IC_ICRC1_LEDGER_WASM_U256_PATH": "$(rootpath :ledger_canister_u256.wasm.gz)",
        "CKBTC_IC_ICRC1_LEDGER_DEPLOYED_VERSION_WASM_PATH": "$(rootpath @mainnet_canisters//:ck_btc_ledger.wasm.gz)",
        "CKETH_IC_ICRC1_LEDGER_DEPLOYED_VERSION_WASM_PATH": "$(rootpath @mainnet_canisters//:ck_eth_ledger.wasm.gz)",
    },
    deps = [
        # Keep sorted.
        ":ledger",
        "//packages/icrc-ledger-types:icrc_ledger_types",
        "//rs/ledger_suite/common/ledger_canister_core",
        "//rs/ledger_suite/icrc1/test_utils",
        "//rs/state_machine_tests",
        "//rs/test_utilities/load_wasm",
        "//rs/types/base_types",
        "@crate_index//:candid",
    ],
)
